package com.westos.core.impl;

import com.westos.bean.RiskBean;
import com.westos.core.ScanRiskSql;
import com.westos.utils.GetCode;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class ScanRiskSqlImpl implements ScanRiskSql {
    private List<RiskBean> list = new ArrayList();//存储漏洞 (文件夹/件名+行数+错误名称+错误代码)
    private List<String> listkeynames = new ArrayList<String>();//存储文件中的request.getParameter()的变量名。

    public List<RiskBean> scan(File file,Integer taskid) {
        String filepath = file.getParent()  + file.getName();
        //System.out.println("开始对"+filepath+"扫描...");
        BufferedReader bufferedReader = null;
        BufferedReader bufferedReader1=null;
        try {
            bufferedReader = new BufferedReader(new FileReader(file));
            //获取文件中的关键变量名
            String line1 = null;
            while ((line1 = bufferedReader.readLine()) != null) {
                if (line1.contains(".getParameter(")) {
                    //String username=request.getParameter("username");
                    //Integer password=Integer.parseInt(request.getParameter("password"));
                    if (line1.contains("=")) {
                        String[] split = line1.split("=");
                        String[] split1 = split[0].split(" ");
                        String name = split1[split1.length - 1];
                        listkeynames.add(name);
                    }

                }
            }

            //找到存在sql注入的代码
            bufferedReader1 = new BufferedReader(new FileReader(file));
            String line = null;
            String fullrowstring = "";
            int num = 0;
            while ((line = bufferedReader1.readLine()) != null) {
                num++;
                fullrowstring += line;
                //要读到有分号，即一个完整的sql语句，才去判断,不能用endwith(),因为代码后面可能有注释
                if (fullrowstring.contains(";")) {
                    //System.out.println(fullrowstring);
                    boolean b = containsSqlInjection(line, listkeynames);//匹配是否为sql注入的代码
                    fullrowstring="";//将上一个完整的一行制空。
                    if (b) {
                        //如果匹配成功，则存在sql注入攻击
                        String riskcode = GetCode.getCodeByNum(file, num);//拿到当前sql注入行的上下文
                        //封装到riskbean
                        RiskBean riskBean = new RiskBean();
                        riskBean.setFilepath(filepath);
                        riskBean.setRownum(num);
                        riskBean.setRiskname("sql注入攻击");
                        riskBean.setRiskcode(riskcode);
                        // TODO: 2019/7/17
                        list.add(riskBean);

                    }
                }

            }



        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
                bufferedReader1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        //System.out.println("此文件扫描结束！");
        return list;
    }


    public static boolean containsSqlInjection(String rowstr, List<String> list) {
        rowstr = rowstr.toLowerCase();//全部转小写
        //去掉java文件中的注释部分代码
        if (rowstr.contains("//")){
            rowstr=rowstr.substring(0,rowstr.indexOf("//"));
        }
        for (String s : list) {
            if (rowstr.contains(s) && rowstr.contains("select") && rowstr.contains("+")) {
                return true;
            }
        }
        return false;
    }


}
